package com.szwistar.iot;

import com.szwistar.common.datastruct.JsonMapper;
import com.szwistar.common.datastruct.Reflector;
import com.szwistar.common.os.FileUtils;

import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CoModelRegistry {
	static final Logger LOG = LoggerFactory.getLogger(CoModelInfo.class);

	// 类 -> Model 登记表
	static Map<Class<?>, CoModelInfo> clazzMap = new HashMap<Class<?>, CoModelInfo>();
	public static CoModelInfo get(Class<?> modelClazz) { return clazzMap.get(modelClazz); }

	// 注册 Model
	public static CoModelInfo register(Class<?> modelClazz) {
		if(get(modelClazz) != null) { return get(modelClazz); }

        // 提取类的注解
		CoModelDef classAnno = modelClazz.getAnnotation(CoModelDef.class);
        // 如果没有注解，就不登记
        if(classAnno == null) { return null; }
        LOG.debug("\tRegister model: {}", classAnno.toString());
        // 生成 Model 信息
        CoModelInfo modelInfo = new CoModelInfo(modelClazz, classAnno);

        // 检查各个字段的注解
		for(Field field : Reflector.getFields(modelClazz)) {
            // 提取属性注解
		    CoAttrDef attrAnno = field.getAnnotation(CoAttrDef.class);
	        // 如果没有注解，就不登记
	        if(attrAnno == null) { continue; }
	        LOG.debug("\t\tRegister attribute: {}", attrAnno.toString());

	        modelInfo.putFieldInfo(new CoAttrInfo(field, attrAnno));
		}

		clazzMap.put(modelClazz, modelInfo);
		return modelInfo;
	}

	public static void exportJson(Class<?> clazz, File dir) throws Exception {
		CoModelInfo modelInfo = register(clazz);
		String json = JsonMapper.toJson(modelInfo);
		File file = new File(dir, clazz.getSimpleName() + ".json");
		FileUtils.writeFile(file, json);
	}

	// for test only
	public static void main(String[] args) throws Exception {
		PropertyConfigurator.configure("log4j.properties");
		LOG.debug("Export ");
		exportJson(TestModel.class, new File("."));
	}
}
